package com.xhwl.data.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.google.common.base.Joiner;
import com.xhwl.common.dto.cent.sdata.PermissionGroupDTO;
import com.xhwl.common.pojo.cent.sdata.Permission;
import com.xhwl.common.pojo.cent.sdata.PermissionGroup;
import com.xhwl.common.pojo.cent.sdata.ProjectPermission;
import com.xhwl.common.pojo.cent.sdata.RolePermission;
import com.xhwl.data.dao.IPermissionGroupDao;
import com.xhwl.data.service.IPermissionGroupService;
import com.xhwl.data.service.IPermissionService;
import com.xhwl.data.service.IProjectPermissionService;
import com.xhwl.data.service.IRolePermissionService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;

import java.util.*;
import java.util.stream.Collectors;

/**
 * @Author: luyi
 * @Description:
 * @Date: Create in 15:30 2022/7/12
 */
@Service
public class PermissionGroupServiceImpl extends ServiceImpl<IPermissionGroupDao, PermissionGroup> implements IPermissionGroupService {

    @Autowired
    private IRolePermissionService rolePermissionService;

    @Autowired
    private IProjectPermissionService projectPermissionService;

    @Autowired
    private IPermissionService permissionService;

    private static final Logger log = LoggerFactory.getLogger(PermissionGroupServiceImpl.class);

    @Override
    public void permissionGroupFilter(List<Integer> ids) {
        QueryWrapper<PermissionGroup> permissionGroupQueryWrapper = new QueryWrapper<>();
        permissionGroupQueryWrapper.isNotNull("project_ids");
        if(!CollectionUtils.isEmpty(ids)){
            permissionGroupQueryWrapper.in("id", ids);
        }
        List<PermissionGroup> permissionGroups = this.list(permissionGroupQueryWrapper);
        if(CollectionUtils.isEmpty(permissionGroups)){
            return;
        }

        Set<Integer> roleIds = new HashSet<>();
        Set<Integer> projectIds = new HashSet<>();

        List<PermissionGroupDTO> permissionGroupDTOS = new ArrayList<>(permissionGroups.size());
        for (PermissionGroup permissionGroup : permissionGroups) {
            Set<Integer> collect = Arrays.asList(permissionGroup.getRoleIds().split(",")).stream().map(i -> Integer.valueOf(i)).collect(Collectors.toSet());
            roleIds.addAll(collect);


            PermissionGroupDTO permissionGroupDTO = new PermissionGroupDTO();
            BeanUtils.copyProperties(permissionGroup, permissionGroupDTO);
            permissionGroupDTO.setRoleList(new ArrayList<>(collect));

            if(!StringUtils.isEmpty(permissionGroup.getProjectIds())){
                Set<Integer> collect1 = Arrays.asList(permissionGroup.getProjectIds().split(",")).stream().map(i -> Integer.valueOf(i)).collect(Collectors.toSet());
                projectIds.addAll(collect1);
                permissionGroupDTO.setProjectList(new ArrayList<>(collect1));
            }
            permissionGroupDTOS.add(permissionGroupDTO);
        }
        if(CollectionUtils.isEmpty(projectIds)){
            return;
        }

        QueryWrapper<RolePermission> rolePermissionQueryWrapper = new QueryWrapper<>();
        rolePermissionQueryWrapper.in("role_id", roleIds);
        List<RolePermission> rolePermissions = rolePermissionService.list(rolePermissionQueryWrapper);

        QueryWrapper<ProjectPermission> projectPermissionQueryWrapper = new QueryWrapper<>();
        projectPermissionQueryWrapper.in("project_id", projectIds);
        List<ProjectPermission> projectPermissions = projectPermissionService.list(projectPermissionQueryWrapper);

        List<Integer> permissionIds = rolePermissions.stream().map(i -> i.getPermissionId()).collect(Collectors.toList());
        permissionIds.addAll(projectPermissions.stream().map(i -> i.getPermissionId()).collect(Collectors.toList()));
        // 查询项目级权限
        QueryWrapper<Permission> permissionQueryWrapper = new QueryWrapper<>();
        permissionQueryWrapper.select("id");
        permissionQueryWrapper.in("id", permissionIds.stream().distinct().collect(Collectors.toList()));
        permissionQueryWrapper.eq("type", 2);
        List<Permission> permissions1 = permissionService.list(permissionQueryWrapper);

        List<Integer> projectPermissionIds = permissions1.stream().map(i -> i.getId()).collect(Collectors.toList());

        // 只针对项目级权限做校验
        Map<Integer, List<Integer>> rolePermissionMap = rolePermissions.stream().filter(i -> projectPermissionIds.contains(i.getPermissionId())).collect(Collectors.groupingBy(RolePermission::getRoleId, Collectors.mapping(RolePermission::getPermissionId, Collectors.toList())));
        Map<Integer, List<Integer>> projectPermissionMap = projectPermissions.stream().filter(i -> projectPermissionIds.contains(i.getPermissionId())).collect(Collectors.groupingBy(ProjectPermission::getProjectId, Collectors.mapping(ProjectPermission::getPermissionId, Collectors.toList())));

        List<PermissionGroup> permissionGroupsUpdate = new ArrayList<>();
        for (PermissionGroupDTO permissionGroup : permissionGroupDTOS) {
            // 项目id为空的权限组，不存在显示问题，故直接跳过
            if(StringUtils.isEmpty(permissionGroup.getProjectIds())){
                continue;
            }
            // 判断 角色权限和项目权限是否有交集，没有交集的需要把项目移除

            // 角色权限集合
            List<Integer> roleList = permissionGroup.getRoleList();
            List<Integer> rolePermissions1 = new ArrayList<>();
            for (Integer integer : roleList) {
                List<Integer> permissions = rolePermissionMap.get(integer);
                if(CollectionUtils.isEmpty(permissions)){
                    continue;
                }
                rolePermissions1.addAll(permissions);
                rolePermissions1 = rolePermissions1.stream().distinct().collect(Collectors.toList());
            }

            // 项目权限集合
            List<Integer> projectList = permissionGroup.getProjectList();

            // 处理需要移除的 project
            List<Integer> removeProjectId = new ArrayList<>();
            for (Integer projectId : projectList) {
                List<Integer> pIds = projectPermissionMap.get(projectId);
                if(CollectionUtils.containsAny(rolePermissions1, pIds)){
                    continue;
                }else{
                    removeProjectId.add(projectId);
                }
            }

            if(!CollectionUtils.isEmpty(removeProjectId)){
                projectList.removeAll(removeProjectId);
                permissionGroup.setProjectIds(Joiner.on(",").join(projectList));
                permissionGroupsUpdate.add(permissionGroup);
            }
        }
        for (PermissionGroup permissionGroup : permissionGroupsUpdate) {
            log.info("更新权限组 {} 信息", permissionGroup.getId());
        }
        this.saveOrUpdateBatch(permissionGroupsUpdate);
    }
}
